package com.zhangzhan.gulimallware.listener;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.rabbitmq.client.Channel;
import com.zhangzhan.gulimallcommcon.tos.ActiveWareUnLockTo;
import com.zhangzhan.gulimallcommcon.tos.WareOrderUnLockTo;
import com.zhangzhan.gulimallcommcon.util.MyCollUtil;
import com.zhangzhan.gulimallcommcon.util.R;
import com.zhangzhan.gulimallware.entity.WareOrderTaskDetailEntity;
import com.zhangzhan.gulimallware.entity.WareOrderTaskEntity;
import com.zhangzhan.gulimallware.feign.OrderFeignService;
import com.zhangzhan.gulimallware.service.WareOrderTaskDetailService;
import com.zhangzhan.gulimallware.service.WareOrderTaskService;
import com.zhangzhan.gulimallware.service.WareSkuService;
import com.zhangzhan.gulimallware.tos.OrderTo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.List;
import java.util.Objects;

import static com.zhangzhan.gulimallcommcon.constant.orderAndWareUnLockCons.WareUnLockConstant.WARE_RELEASE_WARE_QUEUE;

/**
 * @author 张一恒
 * @version 1.0
 * @description:
 * @date 2024/7/2 19:39
 */
@RabbitListener(queues = {WARE_RELEASE_WARE_QUEUE})
@Service
@Slf4j
public class WareUnLockImpl {

    @Autowired
    private OrderFeignService orderFeignService;

    @Autowired
    private WareSkuService wareSkuService;

    @Autowired
    private WareOrderTaskDetailService wareOrderTaskDetailService;

    @Autowired
    private WareOrderTaskService wareOrderTaskService;

    /**
     * 订单超时解锁库存（保险）
     *
     * @param to
     * @param message
     * @param channel
     */
    @RabbitHandler
    @Transactional
    public void delayedUnlocking(WareOrderUnLockTo to, Message message, Channel channel) {
        unLockWare(to, message, channel);
    }

    /**
     * 解锁库存 订单主动发起
     */
    @Transactional
    @RabbitHandler
    public void wareUnLockActive(ActiveWareUnLockTo to, Message message, Channel channel) throws IOException {
        if (StrUtil.isNotBlank(to.getOrderSn())){
            log.info("库存主动解锁，订单号：{}", to.getOrderSn());
            //查询工作单获取工作单id
            List<WareOrderTaskEntity> tasks = wareOrderTaskService.list(Wrappers.<WareOrderTaskEntity>lambdaQuery()
                    .eq(WareOrderTaskEntity::getOrderSn, to.getOrderSn()));

            if (MyCollUtil.isNotEmpty(tasks)) {

                List<Long> taskIds = tasks.stream().map(WareOrderTaskEntity::getId).toList();
                WareOrderUnLockTo wareOrderUnLockTo = new WareOrderUnLockTo();
                wareOrderUnLockTo.setOrderSn(to.getOrderSn());
                wareOrderUnLockTo.setTaskIds(taskIds);
                //解锁
                unLockWare(wareOrderUnLockTo, message, channel);

                log.info("库存主动解锁成功，订单号：{}", to.getOrderSn());
            }
        }
    }


    /**
     * 解锁方法
     * @param to
     * @param message
     * @param channel
     */
    private void unLockWare(WareOrderUnLockTo to, Message message, Channel channel) {
        log.info("进入解锁方法.......");
        try {
            if (Objects.nonNull(to)) {
                //查询订单是否能解锁库存
                R r = orderFeignService.getStateByOrderSn(to.getOrderSn());
                if (Objects.equals(r.getCode(), 0)) {
                    String data = r.getData();
                    if (!Objects.equals(data, "null")) {
                        OrderTo orderTo = JSON.parseObject(r.getData(), OrderTo.class);
                        if ((Objects.isNull(orderTo) || Objects.equals(orderTo.getStatus(), 4) || Objects.equals(orderTo.getStatus(), 5) || Objects.isNull(orderTo.getDeliverySn()))) {
                            //解锁
                            unLock(to, message, channel);
                        } else {
                            //不能解锁 直接丢弃
                            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                        }
                    } else {
                        //解锁
                        unLock(to, message, channel);
                    }
                } else {
                    throw new RuntimeException("远程服务报错");
                }
            }
        } catch (Exception e) {
            log.error("库存解锁失败,MQ或服务异常：" + e.getMessage());
            try {
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
            } catch (IOException ex) {
                log.error("库存解锁失败,代码异常：{}", e.getMessage());
                throw new RuntimeException("库存解锁失败,代码异常：" + e);
            }
            throw new RuntimeException("库存解锁失败,MQ或服务异常：" + e);
        }
    }

    /**
     * 解锁库存&修改工作单状态
     * @param to
     * @param message
     * @param channel
     * @throws Exception
     */
    private void unLock(WareOrderUnLockTo to, Message message, Channel channel) throws Exception {
        for (Long taskId : to.getTaskIds()) {
            WareOrderTaskDetailEntity detail = wareOrderTaskDetailService.getOne(Wrappers.<WareOrderTaskDetailEntity>lambdaQuery()
                    .eq(WareOrderTaskDetailEntity::getTaskId, taskId));
            if (!Objects.isNull(detail)) {
                if (!Objects.isNull(to.getOrderSn()) && !Objects.isNull(detail.getWareId()) && Objects.equals(detail.getState(), 1)) {
                    //可以解锁
                    wareUnLock(detail.getSkuId(), detail.getWareId(), detail.getSkuNum(), channel, message);
                    //解锁成功 修改状态
                    WareOrderTaskDetailEntity detail2 = new WareOrderTaskDetailEntity();
                    detail2.setState(2);
                    wareOrderTaskDetailService.update(detail2, Wrappers.<WareOrderTaskDetailEntity>lambdaUpdate()
                            .eq(WareOrderTaskDetailEntity::getId, detail.getId()));
                    log.info("库存解锁成功，工作单：{}，订单号：{}", detail.getTaskId(), to.getOrderSn());
                }
            }
        }
        //解锁成功/丢弃
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }


    /**
     * @description 解锁库存
     * @param skuId
     * @param wareId
     * @param count
     * @param channel
     * @param message
     * @return void
     * @author zhangyiheng
     * @date 2024/7/3 11:09
     */
    private void wareUnLock(Long skuId, Long wareId, Integer count, Channel channel, Message message) throws IOException {
        //可以解锁
        Boolean unLock = wareSkuService.unLock(skuId, wareId, count);
        if (!unLock) {
            //解锁失败重新放回死信队列
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
            log.error("库存解锁失败,skuId:" + skuId + "仓库id：" + wareId + "解锁数量：" + count);
            throw new RuntimeException("库存解锁失败,skuId:" + skuId + "仓库id：" + wareId + "解锁数量：" + count);
        }
    }

}
